#pragma once

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"
const static int gcap = 5;
template <typename T>
class RingQueue // 单 单
{
public:
    RingQueue(int cap = gcap) : _ring_queue(cap), _cap(cap), _space_sem(cap), _data_sem(0), _p_step(0), _c_step(0)
    {
    }
    void Pop(T *out)
    {
        _data_sem.P();
        {
            LockGuard lockguard(&_consumer_mutex);
            *out = _ring_queue[_c_step++];

            _c_step %= _cap;
        }
        _space_sem.V();
    }
    void Enqueue(const T &in)
    {
        _space_sem.P();
        {
            LockGuard lockguard(&_productor_mutex);
            _ring_queue[_p_step++] = in;

            _p_step %= _cap;
        }
        _data_sem.V();
    }
    ~RingQueue()
    {
    }

private:
    std::vector<T> _ring_queue;
    int _cap;

    Sem _space_sem;
    Sem _data_sem;

    // 生产和消费的位置
    int _p_step;
    int _c_step;

    Mutex _productor_mutex;
    Mutex _consumer_mutex;
};